/**
 * visKMeans.cpp
 * Linux(ubuntu8.04),g++4.3.2
 * Copyright,2/3/2009,LU_CGCAD_THSS_THU_BJ
 * Author: Xinlai,Lu
 */

#include "visKMeans.h"

namespace visualization
{
void visKMeans::relocate(unsigned int itrtNum)
{
	/**
	 * For each streamline, compute and determine the class it belongs to acoording to 
	 * the distance used.
	 */
	for(unsigned int numLn = 0; numLn < getStreamlinesNumber(); numLn++)
	{
//		if(0 == getStreamlineSize(numLn))continue;
		double tmp = DBL_MAX;
		for(unsigned int numCls = 0; numCls < m_NumClusters; numCls++)
		{
			/**Compute the distance between a streamline and a cluster center, and switch the 
			 * class to which 'numLn' belongs to numCls if they are more similar.
			 *
			 * Note that the default distance is Euclidean distance.
			 */
			//double deSim = computeDeSimilarity(numLn, m_ClusterCenters[numCls + itrtNum*m_NumClusters]);

//			/**
//			 * The cluster center used by relocate should be the one of last iteration or the original
//			 * randomly choozed centers.
//			 */
//			if(0 != itrtNum) { itrtNum--; }
//			cout << "numLn	: "<< numLn << "	numCls:	" << numCls << endl;
			if(0 == getClusterCenters(itrtNum, numCls).size())
			{
				cout << "numLn:	" << numLn << endl;
				cout << "numCls:	" << numCls << endl;
			}
			double deSim = computeDeSimilarity(numLn, getClusterCenters(itrtNum, numCls));
//			cout << numLn << " vs " << numCls << "	" << deSim << endl;
			if( tmp > deSim )
			{
				tmp = deSim;
				m_ObjIsClassVec[numLn] = numCls;
			}
		}//for
	}//for
}

_STATUS visKMeans::updateClusterCenters(unsigned int itrtNum)
{
  /* Update the centers, calculate the total error, and then determine the clustering status.
	 * 
	 */
	/**
	 * @Modification 4 : the m_ClassHaveObjVec is slightly modified.
	 */
//	for(unsigned int cls = 0; cls < m_NumClusters; cls++)
//	{
//		m_ClassHaveObjVec[cls].clear();
//	}
	for(unsigned int obj = 0; obj < getStreamlinesNumber(); obj++)
	{
		unsigned int classId = m_ObjIsClassVec[obj];
		/**
		 * @Modification 4.
		 */
		//m_ClassHaveObjVec[classId + itrtNum*m_NumClusters].push_back(obj);
		setClusterMember(itrtNum, classId, obj);
	}
	reshapeCluster2One(DIS_WEIGHTED, itrtNum);

	// If the cluster results have no changes.
	double error = totalError();
	if( abs(error - m_Error) < 1e-6 )
	{
		return _CLUSTERING_END;
	}
	else
	{
		m_Error = error;
		return _CLUSTERING_CONTINUE;
	}
}
}

